package com.opencloud.iot.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.opencloud.common.model.PageParams;
import com.opencloud.iot.client.model.entity.IotConfigs;
import com.opencloud.iot.client.model.entity.IotSleepDataTimeZone;
import com.opencloud.iot.client.model.entity.IotSleepObserver;
import com.opencloud.iot.provider.mapper.IotNStrengMapper;
import com.opencloud.iot.provider.mapper.IotSleepObserverMapper;
import com.opencloud.iot.provider.service.IotCommonService;
import com.opencloud.iot.provider.service.IotConfigsService;
import com.opencloud.iot.provider.service.IotSleepObserverService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 进出记录操作
 * @author yeyong
 */

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class IotSleepObserverServiceImpl implements IotSleepObserverService {

    @Autowired
    private IotNStrengMapper iotNStrengMapper;

    @Autowired
    private IotSleepObserverMapper iotSleepObserverMapper;

    @Autowired
    private IotConfigsService iotConfigsService;

    @Autowired
    private IotCommonService iotCommonService;

    @Override
    public IPage<IotSleepObserver> findListPage(PageParams pageParams) {
        IotSleepObserver query = pageParams.mapToObject(IotSleepObserver.class);
        QueryWrapper<IotSleepObserver> queryWrapper = new QueryWrapper();
        queryWrapper.lambda()
                .eq(ObjectUtils.isNotEmpty(query.getWatchmac()),IotSleepObserver::getWatchmac,query.getWatchmac());
        queryWrapper.lambda().between(ObjectUtils.isNotEmpty(query.getStarttime()) && ObjectUtils.isNotEmpty(query.getEndtime()),IotSleepObserver::getStarttime, query.getStarttime(), query.getEndtime());
        return iotSleepObserverMapper.selectPage(new Page(pageParams.getPage(),pageParams.getLimit()),queryWrapper);
    }


    public List<IotSleepObserver> findListByTimeAndMac(String watchmac,Long startTime,Long endTime,Integer counts) {
       return iotSleepObserverMapper.getSleepObserverByTimeAndMac(watchmac,startTime,endTime,counts);
    }


    public Integer addSleepObserver(IotSleepObserver obj) {
        return iotSleepObserverMapper.insert(obj);
    }


    public Integer updateSleepObserverStatus(IotSleepObserver entity) {
        return iotSleepObserverMapper.updateById(entity);
    }

    @Override
    public Integer createSleepObserverList(Long startTime, Long endTime) {
        int configValue = 0;
        int timeValue = 0;
        int timeSpan = 0;
        double configPercent = 0;
        int Count = 0;
        //1、获取配置规则
            IotConfigs _iotConfigs = iotConfigsService.findConfigByKey("SLEEP");
            if(_iotConfigs!=null){
                configValue = _iotConfigs.getConfigValue();
                timeValue = _iotConfigs.getConfigTimevalue();
                timeSpan = _iotConfigs.getConfigTimespan();
                configPercent = _iotConfigs.getConfigPercent();
                Count = timeSpan / timeValue;
            }
        //2、获取时间段内的手环列表
            List<String> macList = iotNStrengMapper.selectMacList(startTime,endTime);
        //3、遍历手环列表 根据规则获取数据
            for (int i = 0; i < macList.size(); i++) {
                //获取该手环5分钟的原始数据
                String watchmac = macList.get(i);
                List<IotSleepObserver> _ObserverList = iotNStrengMapper.selectSleepData(configValue,watchmac,startTime,endTime);
                //解析原始数据，形成过程数据
                double _currentPercent = 0;
                IotSleepObserver obj = new IotSleepObserver();
                if(_ObserverList.size()>0)
                {
                    IotSleepObserver _m = _ObserverList.get(0);
                    _currentPercent = (_m.getAbovecounts()+_m.getNormalcounts())>0 ? _m.getAbovecounts()*100/(_m.getAbovecounts()+_m.getNormalcounts()) : 0;
                    obj.setAbovecounts(_m.getAbovecounts());
                    obj.setAvgvalue(_m.getAvgvalue());
                    obj.setNormalcounts(_m.getNormalcounts());
                    obj.setStarttime(startTime);
                    obj.setEndtime(endTime);
                    obj.setWatchmac(_m.getWatchmac());
                    obj.setPercent(_currentPercent);
                }
                if(_ObserverList.size()>0) {
                    //判断本次 如果超标 则不处理
                    if (_currentPercent > configPercent) {
                        obj.setStatus(0);
                        this.addSleepObserver(obj);
                    }
                    //如果不超标 则进行处理
                    else {
                        //查找该手环之前的15/5=3条过程数据
                        Long time1 = startTime - timeSpan * 60;
                        Long time2 = endTime;
                        List<IotSleepObserver> _list = findListByTimeAndMac(watchmac, time1, time2, Count - 1);
                        //判断是否达到标准数量的数据
                        if (_list.size() < Count - 1) {
                            //没达到-插入新过程数据
                            obj.setStatus(0);
                            this.addSleepObserver(obj);
                        }
                        //达到 判断是否符合标准
                        else {
                            //符合标准 更新老过程数据 插入新过程数据
                            int goodCount = 1;
                            for (int p = 0; p < _list.size(); p++) {
                                if (_list.get(p).getPercent() <= configPercent) goodCount++;
                            }
                            if (goodCount == Count) {
                                obj.setStatus(1);
                                this.addSleepObserver(obj);
                                //更新前N条
                                for (int p = 0; p < _list.size(); p++) {
                                    IotSleepObserver entity = _list.get(p);
                                    entity.setStatus(1);
                                    this.updateSleepObserverStatus(entity);
                                }
                            }
                            //不符合标准-插入新过程数据
                            else {
                                obj.setStatus(0);
                                this.addSleepObserver(obj);
                            }
                        }
                    }
                }
            }
        return macList.size();
    }


    @Override
    public Integer createSleepObserverTest(Long startTime,Long endTime)
    {
        //1、获取配置
        int configValue = 0;
        int timeValue = 0;
        int timeSpan = 0;
        double configPercent = 0;
        int Count = 0;
        //1、获取配置规则
        IotConfigs _iotConfigs = iotConfigsService.findConfigByKey("SLEEP");
        if(_iotConfigs!=null) {
            configValue = _iotConfigs.getConfigValue();
            timeValue = _iotConfigs.getConfigTimevalue();
            timeSpan = _iotConfigs.getConfigTimespan();
            Count = timeSpan / timeValue;
            configPercent = _iotConfigs.getConfigPercent();
        }
        //2、根据配置获取原始数据的MAC列表（根据CreateTime获取，每10分钟获取一次）
        List<IotSleepDataTimeZone> nStrengsList = iotNStrengMapper.selectMacAndTimeZone(startTime,endTime);
        //3、数据分组（按MAC）
        //4、取每个分组的数据的最大时间和最小时间 创造时间区间
        for (int n=0;n<nStrengsList.size();n++)
        {
            IotSleepDataTimeZone entry = nStrengsList.get(n);
            String watchmac = entry.getWatchmac();
            Date minTime_date = entry.getMintime();
            Date maxTime_date = entry.getMaxtime();
            // 创造时间区间

            Long minTime_long = iotCommonService.CreateMinTime(timeValue,minTime_date);
            Long maxTime_long = iotCommonService.CreateMaxTime(timeValue,maxTime_date);

            //5、遍历时间区间
            int s = (timeValue*60);
            int x = (int)((maxTime_long-minTime_long)/s);
            for(int i=0;i<x;i++)
            {
                Long stime1 = minTime_long+i*s;
                Long stime2 = minTime_long+(i+1)*s-1;
                //取原始数据
                List<IotSleepObserver> _ObserverList = iotNStrengMapper.selectSleepData(configValue,watchmac,stime1,stime2);
                //解析原始数据，形成过程数据
                double _currentPercent = 0;
                IotSleepObserver obj = new IotSleepObserver();
                if(_ObserverList.size()>0)
                {
                    /**
                     * 睡眠状态
                     * status=0 初始状态 未入睡
                     * status=1 已入睡
                     * status=2 可能睡
                     * status=3 可能醒
                     * status=4 已醒
                     */
                    System.out.println("有原始数据");
                    IotSleepObserver _m = _ObserverList.get(0);
                    _currentPercent = (_m.getAbovecounts()+_m.getNormalcounts())>0 ? _m.getAbovecounts()*100/(_m.getAbovecounts()+_m.getNormalcounts()) : 0;
                    obj.setAbovecounts(_m.getAbovecounts());
                    obj.setAvgvalue(_m.getAvgvalue());
                    obj.setNormalcounts(_m.getNormalcounts());
                    obj.setStarttime(stime1);
                    obj.setEndtime(stime2);
                    obj.setWatchmac(watchmac);
                    obj.setPercent(_currentPercent);
                    int status = 0;
                    //取前一条数据的状态来修正当前数据的状态
                    Long _preStime = minTime_long+(i-1)*s;
                    Long _preEtime = minTime_long+i*s-1;
                    List<IotSleepObserver> _preData = iotSleepObserverMapper.getSleepObserverByTimeAndMac(watchmac,_preStime,_preEtime,1);
                    if(_preData.size()>0)
                    {
                        if(_currentPercent <= configPercent)
                        {
                            if(_preData.get(0).getStatus()==1){
                                status = 1;
                            }else{
                                status = 2;
                            }
                        } else{
                            if(_preData.get(0).getStatus()==0){
                                status = 0;
                            }else if(_preData.get(0).getStatus()==1){
                                status = 3;
                            }else if(_preData.get(0).getStatus()==2){
                                status = 3;
                            }else if(_preData.get(0).getStatus()==3){
                                status = 3;
                            }else if(_preData.get(0).getStatus()==4){
                                status = 4;
                            }
                        }
                    }else{
                        status= 0;
                    }

                    //6、取过程数据
                    List<IotSleepObserver> _dataList = iotSleepObserverMapper.getSleepObserverByTimeAndMac(watchmac,stime1,stime2,1);
                    //判断是否有过程数据 有更新 无添加
                    if(_dataList.size()>0)
                    {
                        System.out.println("有过程数据");
                        int id = _dataList.get(0).getId();
                        obj.setId(id);
                        this.iotSleepObserverMapper.updateById(obj);
                    }else {
                        System.out.println("无过程数据");
                        obj.setStatus(status);
                        this.iotSleepObserverMapper.insert(obj);
                    }
                    //7、数据修正

                        System.out.println("数据修正开始");
                        //查找该手环之前的15/5=3条过程数据
                        ///都大于配置值 则修正为已入睡
                        Long time1 = stime1 - timeSpan * 60;
                        Long time2 = stime2;
                        List<IotSleepObserver> _list = findListByTimeAndMac(watchmac, time1, time2, Count);
                        int goodCount = 0;
                        int badCount = 0;
                        for (int p = 0; p < _list.size(); p++) {
                            if (_list.get(p).getPercent() <= configPercent) goodCount++;
                            if (_list.get(p).getPercent() > configPercent) badCount++;
                        }


                        if (goodCount == Count) {
                            status = 1;
                        }
                        if(badCount==Count)
                        {
                            status = 4;
                        }
                        //更新前N条
                        if(status==1 || status==4) {
                            for (int p = 0; p < _list.size(); p++) {
                                IotSleepObserver entity = _list.get(p);
                                entity.setStatus(status);
                                System.out.println("更新数据数量:" + (p + 1) + "条");
                                this.updateSleepObserverStatus(entity);
                            }
                        }
                }
            }
        }
        return nStrengsList.size();
    }
}
